home *** CD-ROM | disk | FTP | other *** search
/ Micromanía 92 / CDMM92_1.ISO / SOF 2 SDK / sof2sdk-101.msi / _92D6AC311BB48EBA344BBABC89DA6AB0 / _C3C03A975F7241D297BA15E0BB9E7049 < prev    next >
Encoding:
Text File  |  2002-06-05  |  12.1 KB  |  504 lines

  1. // Copyright (C) 2001-2002 Raven Software.
  2. //
  3. // cg_snapshot.c -- things that happen on snapshot transition,
  4. // not necessarily every single rendered frame
  5.  
  6. #include "cg_local.h"
  7.  
  8. /*
  9. ==================
  10. CG_ResetEntity
  11. ==================
  12. */
  13. static void CG_ResetEntity( centity_t *cent ) 
  14. {
  15.     // if the previous snapshot this entity was updated in is at least
  16.     // an event window back in time then we can reset the previous event
  17.     if ( cent->snapShotTime < cg.time - EVENT_VALID_MSEC ) 
  18.     {
  19.         cent->previousEvent = 0;
  20.     }
  21.  
  22.     cent->trailTime = cg.snap->serverTime;
  23.  
  24.     VectorCopy (cent->currentState.origin, cent->lerpOrigin);
  25.     VectorCopy (cent->currentState.angles, cent->lerpAngles);
  26.     if ( cent->currentState.eType == ET_PLAYER ) 
  27.     {
  28.         CG_ResetPlayerEntity( cent );
  29.     }
  30.  
  31.     cent->pe.weapon = 0;
  32. }
  33.  
  34. /*
  35. ===============
  36. CG_TransitionEntity
  37.  
  38. cent->nextState is moved to cent->currentState and events are fired
  39. ===============
  40. */
  41. static void CG_TransitionEntity( centity_t *cent ) 
  42. {
  43.     cent->currentState = cent->nextState;
  44.     cent->currentValid = qtrue;
  45.  
  46.     // reset if the entity wasn't in the last frame or was teleported
  47.     if ( !cent->interpolate ) {
  48.         CG_ResetEntity( cent );
  49.     }
  50.  
  51.     // Time is overloaded for players to store the spawn count, so when a player is newly spawned
  52.     // their gore should be reset
  53.     if ( cent->pe.spawnCount != cent->currentState.time )
  54.     {
  55.         cent->pe.spawnCount = cent->currentState.time;
  56.  
  57.         // Force all the animations to be restarted
  58.         cent->pe.torso.anim = -1;
  59.         cent->pe.legs.anim = -1;
  60.  
  61.         if ( cent->ghoul2 )
  62.         {
  63.             trap_G2API_ClearSkinGore ( cent->ghoul2 );
  64.         }
  65.     }
  66.  
  67.     // clear the next state.  if will be set by the next CG_SetNextSnap
  68.     cent->interpolate = qfalse;
  69.  
  70.     // check for events
  71.     CG_CheckEvents( cent );
  72. }
  73.  
  74.  
  75. /*
  76. ==================
  77. CG_SetInitialSnapshot
  78.  
  79. This will only happen on the very first snapshot, or
  80. on map restarts.  All other times will use 
  81. CG_TransitionSnapshot instead.
  82.  
  83. FIXME: Also called by map_restart?
  84. ==================
  85. */
  86. void CG_SetInitialSnapshot( snapshot_t *snap ) 
  87. {
  88.     int                i;
  89.     centity_t        *cent;
  90.     entityState_t    *state;
  91.  
  92.     cg.snap = snap;
  93.  
  94.     cent = CG_GetEntity ( snap->ps.clientNum );
  95.  
  96.     if (!cgs.clientinfo[snap->ps.clientNum].ghoul2Model)
  97.     {
  98.         Com_Error(ERR_DROP, "CG_SetInitialSnapshot invalid g2 pointer for client\n");
  99.     }
  100.  
  101.     if ((cent->ghoul2 == NULL) && trap_G2_HaveWeGhoul2Models(cgs.clientinfo[snap->ps.clientNum].ghoul2Model))
  102.     {
  103.         trap_G2API_DuplicateGhoul2Instance(cgs.clientinfo[snap->ps.clientNum].ghoul2Model, ¢->ghoul2);
  104.     }
  105.  
  106.     BG_PlayerStateToEntityState( &snap->ps, ¢->currentState, qfalse );
  107.  
  108.     // sort out solid entities
  109.     CG_BuildSolidList();
  110.  
  111.     CG_ExecuteNewServerCommands( snap->serverCommandSequence );
  112.  
  113.     // set our local weapon selection pointer to
  114.     // what the server has indicated the current weapon is
  115.     CG_Respawn();
  116.  
  117.     for ( i = 0 ; i < cg.snap->numEntities ; i++ ) 
  118.     {
  119.         state = &cg.snap->entities[ i ];
  120.         cent = CG_GetEntity ( state->number );
  121.  
  122.         memcpy(¢->currentState, state, sizeof(entityState_t));
  123.         //cent->currentState = *state;
  124.         cent->interpolate = qfalse;
  125.         cent->currentValid = qtrue;
  126.  
  127.         CG_ResetEntity( cent );
  128.  
  129.         // check for events
  130.         CG_CheckEvents( cent );
  131.     }
  132. }
  133.  
  134.  
  135. /*
  136. ===================
  137. CG_TransitionSnapshot
  138.  
  139. The transition point from snap to nextSnap has passed
  140. ===================
  141. */
  142. static void CG_TransitionSnapshot( void ) 
  143. {
  144.     centity_t    *cent;
  145.     snapshot_t    *oldFrame;
  146.     int            i;
  147.  
  148.     if ( !cg.snap ) 
  149.     {
  150.         Com_Error( ERR_FATAL, "CG_TransitionSnapshot: NULL cg.snap" );
  151.     }
  152.  
  153.     if ( !cg.nextSnap ) 
  154.     {
  155.         Com_Error( ERR_FATAL, "CG_TransitionSnapshot: NULL cg.nextSnap" );
  156.     }
  157.  
  158.     // execute any server string commands before transitioning entities
  159.     CG_ExecuteNewServerCommands( cg.nextSnap->serverCommandSequence );
  160.  
  161.     // if we had a map_restart, set everthing with initial
  162.     if ( !cg.snap ) 
  163.     {
  164.     }
  165.  
  166.     // clear the currentValid flag for all entities in the existing snapshot
  167.     for ( i = 0 ; i < cg.snap->numEntities ; i++ ) 
  168.     {
  169.         cent = CG_GetEntity ( cg.snap->entities[ i ].number );
  170.         cent->currentValid = qfalse;
  171.     }
  172.  
  173.     // move nextSnap to snap and do the transitions
  174.     oldFrame = cg.snap;
  175.     cg.snap = cg.nextSnap;
  176.  
  177.     cent = CG_GetEntity ( cg.snap->ps.clientNum );
  178.     BG_PlayerStateToEntityState( &cg.snap->ps, ¢->currentState, qfalse );
  179.     cent->interpolate = qfalse;
  180.     cent->currentValid = qtrue;
  181.  
  182.     for ( i = 0 ; i < cg.snap->numEntities ; i++ ) 
  183.     {
  184.         // Transition the entity
  185.         cent = CG_GetEntity ( cg.snap->entities[ i ].number );
  186.         CG_TransitionEntity( cent );
  187.  
  188.         // remember time of snapshot this entity was last updated in
  189.         cent->snapShotTime = cg.snap->serverTime;
  190.     }
  191.  
  192.     cg.nextSnap = NULL;
  193.  
  194.     // check for playerstate transition events
  195.     if ( oldFrame ) 
  196.     {
  197.         playerState_t    *ops, *ps;
  198.  
  199.         ops = &oldFrame->ps;
  200.         ps = &cg.snap->ps;
  201.         
  202.         // teleporting checks are irrespective of prediction
  203.         if ( ( ps->eFlags ^ ops->eFlags ) & EF_TELEPORT_BIT ) 
  204.         {
  205.             cg.thisFrameTeleport = qtrue;    // will be cleared by prediction code
  206.         }
  207.  
  208.         // if we are not doing client side movement prediction for any
  209.         // reason, then the client events and view changes will be issued now
  210.         if ( cg.demoPlayback || (cg.snap->ps.pm_flags & PMF_FOLLOW)
  211.             || cg_nopredict.integer || cg_synchronousClients.integer ) 
  212.         {
  213.             CG_TransitionPlayerState( ps, ops );
  214.         }
  215.     }
  216. }
  217.  
  218. /*
  219. ===================
  220. CG_SetNextSnap
  221.  
  222. A new snapshot has just been read in from the client system.
  223. ===================
  224. */
  225. static void CG_SetNextSnap( snapshot_t *snap ) 
  226. {
  227.     int                    num;
  228.     entityState_t        *es;
  229.     centity_t            *cent;
  230.  
  231.     cg.nextSnap = snap;
  232.  
  233.     cent = CG_GetEntity ( snap->ps.clientNum );
  234.  
  235.     BG_PlayerStateToEntityState( &snap->ps, ¢->nextState, qfalse );
  236.     cent->interpolate = qtrue;
  237.  
  238.     // check for extrapolation errors
  239.     for ( num = 0 ; num < snap->numEntities ; num++ ) 
  240.     {
  241.         es = &snap->entities[num];
  242.         cent = CG_GetEntity ( es->number );
  243.  
  244.         memcpy(¢->nextState, es, sizeof(entityState_t));
  245.         //cent->nextState = *es;
  246.  
  247.         // if this frame is a teleport, or the entity wasn't in the
  248.         // previous frame, don't interpolate
  249.         if ( !cent->currentValid || ( ( cent->currentState.eFlags ^ es->eFlags ) & EF_TELEPORT_BIT )  ) 
  250.         {
  251.             cent->interpolate = qfalse;
  252.         } 
  253.         else 
  254.         {
  255.             cent->interpolate = qtrue;
  256.         }
  257.     }
  258.  
  259.     // if the next frame is a teleport for the playerstate, we
  260.     // can't interpolate during demos
  261.     if ( cg.snap && ( ( snap->ps.eFlags ^ cg.snap->ps.eFlags ) & EF_TELEPORT_BIT ) ) 
  262.     {
  263.         cg.nextFrameTeleport = qtrue;
  264.     } 
  265.     else 
  266.     {
  267.         cg.nextFrameTeleport = qfalse;
  268.     }
  269.  
  270.     // if changing follow mode, don't interpolate
  271.     if ( cg.nextSnap->ps.clientNum != cg.snap->ps.clientNum ) 
  272.     {
  273.         cg.nextFrameTeleport = qtrue;
  274.     }
  275.  
  276.     // if changing server restarts, don't interpolate
  277.     if ( ( cg.nextSnap->snapFlags ^ cg.snap->snapFlags ) & SNAPFLAG_SERVERCOUNT ) 
  278.     {
  279.         cg.nextFrameTeleport = qtrue;
  280.     }
  281.  
  282.     // sort out solid entities
  283.     CG_BuildSolidList();
  284. }
  285.  
  286.  
  287. /*
  288. ========================
  289. CG_ReadNextSnapshot
  290.  
  291. This is the only place new snapshots are requested
  292. This may increment cgs.processedSnapshotNum multiple
  293. times if the client system fails to return a
  294. valid snapshot.
  295. ========================
  296. */
  297. static snapshot_t *CG_ReadNextSnapshot( void ) {
  298.     qboolean    r;
  299.     snapshot_t    *dest;
  300.  
  301.     if ( cg.latestSnapshotNum > cgs.processedSnapshotNum + 1000 ) {
  302.         Com_Printf( "WARNING: CG_ReadNextSnapshot: way out of range, %i > %i", 
  303.             cg.latestSnapshotNum, cgs.processedSnapshotNum );
  304.     }
  305.  
  306.     while ( cgs.processedSnapshotNum < cg.latestSnapshotNum ) {
  307.  
  308.     /*
  309.         // decide which of the two slots to load it into
  310.         if ( cg.snap == &cg.activeSnapshots[0] ) {
  311.             dest = &cg.activeSnapshots[1];
  312.         } else {
  313.             dest = &cg.activeSnapshots[0];
  314.         }
  315.     */
  316.         dest = &cg.activeSnapshots[cg.activeSnapshot%3];
  317.  
  318.         // try to read the snapshot from the client system
  319.         cgs.processedSnapshotNum++;
  320.         r = trap_GetSnapshot( cgs.processedSnapshotNum, dest );
  321.  
  322.         // FIXME: why would trap_GetSnapshot return a snapshot with the same server time
  323.         if ( cg.nextSnap && r && dest->serverTime == cg.nextSnap->serverTime ) {
  324. //            r = r;
  325. //            continue;
  326.         }
  327.  
  328.         // if it succeeded, return
  329.         if ( r ) {
  330.             cg.activeSnapshot++;
  331.             CG_AddLagometerSnapshotInfo( dest );
  332.             return dest;
  333.         }
  334.  
  335.         // a GetSnapshot will return failure if the snapshot
  336.         // never arrived, or  is so old that its entities
  337.         // have been shoved off the end of the circular
  338.         // buffer in the client system.
  339.  
  340.         // record as a dropped packet
  341.         CG_AddLagometerSnapshotInfo( NULL );
  342.  
  343.         // If there are additional snapshots, continue trying to
  344.         // read them.
  345.     }
  346.  
  347.     // nothing left to read
  348.     return NULL;
  349. }
  350.  
  351.  
  352. /*
  353. ============
  354. CG_ProcessSnapshots
  355.  
  356. We are trying to set up a renderable view, so determine
  357. what the simulated time is, and try to get snapshots
  358. both before and after that time if available.
  359.  
  360. If we don't have a valid cg.snap after exiting this function,
  361. then a 3D game view cannot be rendered.  This should only happen
  362. right after the initial connection.  After cg.snap has been valid
  363. once, it will never turn invalid.
  364.  
  365. Even if cg.snap is valid, cg.nextSnap may not be, if the snapshot
  366. hasn't arrived yet (it becomes an extrapolating situation instead
  367. of an interpolating one)
  368.  
  369. ============
  370. */
  371. void CG_ProcessSnapshots( void ) 
  372. {
  373.     snapshot_t        *snap;
  374.     int                n;
  375.  
  376.     // see what the latest snapshot the client system has is
  377.     trap_GetCurrentSnapshotNumber( &n, &cg.latestSnapshotTime );
  378.     if ( n != cg.latestSnapshotNum ) 
  379.     {
  380.         if ( n < cg.latestSnapshotNum ) 
  381.         {
  382.             // this should never happen
  383.             Com_Error( ERR_FATAL, "CG_ProcessSnapshots: n < cg.latestSnapshotNum" );
  384.         }
  385.         cg.latestSnapshotNum = n;
  386.     }
  387.  
  388.     // If we have yet to receive a snapshot, check for it.
  389.     // Once we have gotten the first snapshot, cg.snap will
  390.     // always have valid data for the rest of the game
  391.     while ( !cg.snap ) 
  392.     {
  393.         snap = CG_ReadNextSnapshot();
  394.     
  395.         if ( !snap ) 
  396.         {
  397.             // we can't continue until we get a snapshot
  398.             return;
  399.         }
  400.  
  401.         // set our weapon selection to what
  402.         // the playerstate is currently using
  403.         if ( !( snap->snapFlags & SNAPFLAG_NOT_ACTIVE ) ) 
  404.         {
  405.             CG_SetInitialSnapshot( snap );
  406.         }
  407.     }
  408.  
  409.     // loop until we either have a valid nextSnap with a serverTime
  410.     // greater than cg.time to interpolate towards, or we run
  411.     // out of available snapshots
  412.     do 
  413.     {
  414.         // if we don't have a nextframe, try and read a new one in
  415.         if ( !cg.nextSnap || cg.needNextSnap ) // !cg.nextSnap ) 
  416.         {
  417.             snap = CG_ReadNextSnapshot();
  418.  
  419.             // if we still don't have a nextframe, we will just have to
  420.             // extrapolate
  421.             if ( !snap ) 
  422.             {
  423.                 if ( cg_drawSnapshot.integer )
  424.                     Com_Printf ( "NOSNAP\n" );
  425.  
  426.  
  427.                 break;
  428.             }
  429.  
  430. #ifdef _SNAPSHOT_EXTRAPOLATION
  431.  
  432.             cg.needNextSnap = qfalse;
  433.  
  434.             if ( cg.nextSnap)
  435.             {
  436.                 if ( cg_drawSnapshot.integer )
  437.                     Com_Printf ( "TRANS\n" );
  438.  
  439.                 CG_TransitionSnapshot();
  440.             }
  441. #endif
  442.  
  443.             CG_SetNextSnap( snap );
  444.  
  445.  
  446.             // if time went backwards, we have a level restart
  447.             if ( cg.nextSnap->serverTime < cg.snap->serverTime ) 
  448.             {
  449.                 Com_Error( ERR_FATAL, "CG_ProcessSnapshots: Server time went backwards" );
  450.             }
  451.         }
  452.  
  453. #ifdef _SNAPSHOT_EXTRAPOLATION
  454.  
  455.         if ( cg.needNextSnap )
  456.         {
  457.                 if ( cg_drawSnapshot.integer )
  458.                     Com_Printf ( "NEED\n" );
  459.  
  460.             break;
  461.         }
  462.  
  463. #endif
  464.  
  465.         // if our time is < nextFrame's, we have a nice interpolating state
  466.         if ( cg.time >= cg.snap->serverTime && cg.time < cg.nextSnap->serverTime ) 
  467.         {
  468.             break;
  469.         }
  470.  
  471. #ifdef _SNAPSHOT_EXTRAPOLATION
  472.  
  473.         cg.needNextSnap = qtrue;
  474.  
  475.         if ( cg_drawSnapshot.integer )
  476.             Com_Printf ( "SNAP:  time=%i\n", cg.time );
  477.  
  478. #else
  479.         // we have passed the transition from nextFrame to frame
  480.         CG_TransitionSnapshot();
  481. #endif
  482.     
  483.     } while ( 1 );
  484.  
  485.     // assert our valid conditions upon exiting
  486.     if ( cg.snap == NULL ) 
  487.     {
  488.         Com_Error( ERR_FATAL, "CG_ProcessSnapshots: cg.snap == NULL" );
  489.     }
  490.     
  491.     if ( cg.time < cg.snap->serverTime ) 
  492.     {
  493.         // this can happen right after a vid_restart
  494.         cg.time = cg.snap->serverTime;
  495.     }
  496.  
  497. #ifndef _SNAPSHOT_EXTRAPOLATION    
  498.     if ( cg.nextSnap != NULL && cg.nextSnap->serverTime <= cg.time ) 
  499.     {
  500.         Com_Error( ERR_FATAL, "CG_ProcessSnapshots: cg.nextSnap->serverTime <= cg.time" );
  501.     }
  502. #endif
  503. }
  504.